package com.ochnas.volunteersignup;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.WebApplicationContext;
import org.mortbay.jetty.handler.ContextHandlerCollection;
import org.mortbay.jetty.handler.ContextHandler;
import org.mortbay.jetty.servlet.PathMap;
import org.mortbay.jetty.webapp.WebAppContext;

import java.lang.reflect.Field;


public abstract class SpringLoader {

    // This is the spring application context that starts jetty up
    public static ApplicationContext jettyContext = new ClassPathXmlApplicationContext("testApplicationContext.xml");

    // ALL Unit tests should use this spring application contexts
    public static ApplicationContext spring;


    // Somewhat hokey logic that uses insider information about the jetty server to pull the web application
    // context out of the Servlet context so that we don't try to start another instance of the ActiveMQ server
    // NOTE: All unit tests that need to interact with services defined in the web application should use this
    // spring instance and not create their own.  Creating their own will result in an attempt to create another
    // ActiveMQ instance which will fail
    static {
        ContextHandlerCollection ctxHandlrCol = (ContextHandlerCollection)((org.mortbay.jetty.Server)
                jettyContext.getBean("server")).getHandlers()[0];
        PathMap pathMap = (PathMap) getPrivateField(ctxHandlrCol, "_contextMap");
        WebAppContext webAppContext = (WebAppContext) pathMap.get("/");
        ContextHandler.Context ctx = (ContextHandler.Context) getPrivateField(webAppContext, "_context");
        spring = (ApplicationContext) ctx.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
    }

    private static Object getPrivateField(Object o, String field) {
        Class c = o.getClass();
        do {
            for (Field f : c.getDeclaredFields()) {
                if (f.getName().equals(field)) {
                    f.setAccessible(true);
                    try {
                        return f.get(o);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException("Error loading spring: ",e);
                    }
                }
            }
            c = c.getSuperclass();
        } while (c != null);

        throw new RuntimeException("No field called "+field+" found on "+o);
    }
}
